// Cz Exokernel - 极简内核，只提供安全的硬件多路复用
// 
// Exokernel 理念：
// 1. 内核只负责资源保护和多路复用
// 2. 所有抽象（文件系统、网络栈等）在用户态实现
// 3. 应用直接访问硬件（通过安全检查）

// 简化的内存管理（内联）
const PAGE_SIZE: usize = 4096;

const PhysicalAllocator = struct {
    bitmap: []u8,
    total_pages: usize,
    used_pages: usize,
    
    pub fn init(allocator: anytype, memory_size: usize) !PhysicalAllocator {
        const total_pages = memory_size / PAGE_SIZE;
        const bitmap_size = (total_pages + 7) / 8;
        
        const bitmap = try allocator.alloc(u8, bitmap_size);
        @memset(bitmap, 0);
        
        return .{
            .bitmap = bitmap,
            .total_pages = total_pages,
            .used_pages = 0,
        };
    }
    
    pub fn deinit(self: *PhysicalAllocator, allocator: anytype) void {
        allocator.free(self.bitmap);
    }
    
    pub fn alloc_page(self: *PhysicalAllocator) ?usize {
        var i: usize = 0;
        while (i < self.total_pages) : (i += 1) {
            const byte_idx = i / 8;
            const bit_idx = @as(u3, @intCast(i % 8));
            
            if ((self.bitmap[byte_idx] & (@as(u8, 1) << bit_idx)) == 0) {
                self.bitmap[byte_idx] |= (@as(u8, 1) << bit_idx);
                self.used_pages += 1;
                return i * PAGE_SIZE;
            }
        }
        return null;
    }
    
    pub fn free_page(self: *PhysicalAllocator, addr: usize) void {
        const page_idx = addr / PAGE_SIZE;
        const byte_idx = page_idx / 8;
        const bit_idx = @as(u3, @intCast(page_idx % 8));
        
        // 检查是否已分配
        if ((self.bitmap[byte_idx] & (@as(u8, 1) << bit_idx)) != 0) {
            self.bitmap[byte_idx] &= ~(@as(u8, 1) << bit_idx);
            self.used_pages -= 1;
        }
    }
};

/// Exokernel 只管理这些基本资源
pub const Resource = enum {
    physical_page,      // 物理内存页
    cpu_time,          // CPU 时间片
    disk_block,        // 磁盘块
    network_packet,    // 网络包
    interrupt_vector,  // 中断向量
};

/// 资源能力（Capability）- 访问资源的凭证
pub const Capability = struct {
    resource: Resource,
    id: u32,           // 资源 ID
    owner: u32,        // 拥有者（LibOS ID）
    permissions: u8,   // 权限位
    
    pub fn check(self: *const Capability, libos_id: u32, perm: u8) bool {
        return self.owner == libos_id and (self.permissions & perm) != 0;
    }
};

/// LibOS（用户态操作系统库）
pub const LibOS = struct {
    id: u32,
    name: [32]u8,
    entry_point: usize,
    
    // 资源表
    capabilities: [256]?Capability,
    cap_count: u16,
    
    // 内存映射
    page_table: usize,
    
    pub fn init(id: u32, name: []const u8, entry: usize) LibOS {
        var self: LibOS = undefined;
        self.id = id;
        self.entry_point = entry;
        self.cap_count = 0;
        
        // 复制名称
        var i: usize = 0;
        while (i < name.len and i < 32) : (i += 1) {
            self.name[i] = name[i];
        }
        
        // 初始化能力表
        i = 0;
        while (i < 256) : (i += 1) {
            self.capabilities[i] = null;
        }
        
        return self;
    }
    
    pub fn grant_capability(self: *LibOS, cap: Capability) bool {
        if (self.cap_count >= 256) return false;
        
        self.capabilities[self.cap_count] = cap;
        self.cap_count += 1;
        return true;
    }
    
    pub fn has_capability(self: *const LibOS, resource: Resource, id: u32) bool {
        var i: u16 = 0;
        while (i < self.cap_count) : (i += 1) {
            if (self.capabilities[i]) |cap| {
                if (cap.resource == resource and cap.id == id) {
                    return true;
                }
            }
        }
        return false;
    }
};

/// Exokernel 核心
pub const Exokernel = struct {
    // LibOS 表
    libos_table: [16]?LibOS,
    libos_count: u8,
    current_libos: u8,
    
    // 资源管理
    phys_allocator: PhysicalAllocator,
    
    pub fn init(allocator: anytype, mem_size: usize) !Exokernel {
        var self: Exokernel = undefined;
        
        self.libos_count = 0;
        self.current_libos = 0;
        
        // 初始化物理内存分配器
        self.phys_allocator = try PhysicalAllocator.init(allocator, mem_size);
        
        // 初始化 LibOS 表
        var i: u8 = 0;
        while (i < 16) : (i += 1) {
            self.libos_table[i] = null;
        }
        
        return self;
    }
    
    pub fn deinit(self: *Exokernel, allocator: anytype) void {
        self.phys_allocator.deinit(allocator);
    }
    
    /// 注册新的 LibOS
    pub fn register_libos(self: *Exokernel, name: []const u8, entry: usize) ?u32 {
        if (self.libos_count >= 16) return null;
        
        const id = self.libos_count;
        self.libos_table[id] = LibOS.init(id, name, entry);
        self.libos_count += 1;
        
        return id;
    }
    
    /// 系统调用：分配物理页
    pub fn syscall_alloc_page(self: *Exokernel, libos_id: u32) ?Capability {
        // 检查 LibOS 是否存在
        if (libos_id >= self.libos_count) return null;
        
        // 分配物理页
        const page_addr = self.phys_allocator.alloc_page() orelse return null;
        const page_id = @as(u32, @intCast(page_addr / PAGE_SIZE));
        
        // 创建能力
        const cap = Capability{
            .resource = .physical_page,
            .id = page_id,
            .owner = libos_id,
            .permissions = 0b111, // 读写执行
        };
        
        // 授予能力
        if (self.libos_table[libos_id]) |*libos| {
            if (libos.grant_capability(cap)) {
                return cap;
            }
        }
        
        // 失败，释放页
        self.phys_allocator.free_page(page_addr);
        return null;
    }
    
    /// 系统调用：释放物理页
    pub fn syscall_free_page(self: *Exokernel, libos_id: u32, page_id: u32) bool {
        if (libos_id >= self.libos_count) return false;
        
        // 检查能力
        if (self.libos_table[libos_id]) |libos| {
            if (!libos.has_capability(.physical_page, page_id)) {
                return false; // 没有权限
            }
        } else {
            return false;
        }
        
        // 释放页
        const page_addr = page_id * PAGE_SIZE;
        self.phys_allocator.free_page(page_addr);
        
        return true;
    }
    
    /// 系统调用：映射物理页到虚拟地址
    pub fn syscall_map_page(
        self: *Exokernel,
        libos_id: u32,
        page_id: u32,
        virt_addr: usize,
    ) bool {
        if (libos_id >= self.libos_count) return false;
        
        // 检查能力
        if (self.libos_table[libos_id]) |libos| {
            if (!libos.has_capability(.physical_page, page_id)) {
                return false;
            }
        } else {
            return false;
        }
        
        // TODO: 实际的页表映射
        _ = virt_addr;
        
        return true;
    }
    
    /// 系统调用：让出 CPU
    pub fn syscall_yield(self: *Exokernel) void {
        // 简单的轮询调度
        self.current_libos = (self.current_libos + 1) % self.libos_count;
    }
    
    /// 调度下一个 LibOS
    pub fn schedule(self: *Exokernel) ?*LibOS {
        if (self.libos_count == 0) return null;
        
        const libos_id = self.current_libos;
        self.current_libos = (self.current_libos + 1) % self.libos_count;
        
        return if (self.libos_table[libos_id]) |*libos| libos else null;
    }
};

/// Exokernel 系统调用接口
pub const Syscall = enum(u32) {
    alloc_page = 0,
    free_page = 1,
    map_page = 2,
    yield = 3,
    send_packet = 4,
    recv_packet = 5,
    disk_read = 6,
    disk_write = 7,
};

/// 系统调用处理器
pub fn handle_syscall(
    exo: *Exokernel,
    syscall: Syscall,
    libos_id: u32,
    arg1: u32,
    arg2: u32,
) u32 {
    return switch (syscall) {
        .alloc_page => {
            if (exo.syscall_alloc_page(libos_id)) |cap| {
                return cap.id;
            }
            return 0xFFFFFFFF; // 失败
        },
        .free_page => {
            return if (exo.syscall_free_page(libos_id, arg1)) 1 else 0;
        },
        .map_page => {
            return if (exo.syscall_map_page(libos_id, arg1, arg2)) 1 else 0;
        },
        .yield => {
            exo.syscall_yield();
            return 0;
        },
        else => 0xFFFFFFFF, // 未实现
    };
}
